﻿using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;

namespace CloudStorageLight.Core
{
    public abstract class BlobAdapterBase : MarshalByRefObject //, IBlobAdapter
    {
        public virtual BlobContainer Parent { get; set; }
        public virtual string RootPath { get; set; }

        public virtual string TimeZone { get; set; }

        /// <summary>
        /// 指定したファイルが存在するか
        /// </summary>
        /// <param name="path2"></param>
        /// <returns></returns>
        public async virtual Task<bool> ExistsAsync(string path)
        {
            if (ExistsCahce.Keys.Contains(path)) return ExistsCahce[path];
            ExistsCahce[path] = await ExistsAsyncInternal(path);

            return ExistsCahce[path];
        }
        protected Dictionary<string, bool> ExistsCahce = new Dictionary<string, bool>();

        /// <summary>
        /// 指定したファイルが存在するか(内部)
        /// </summary>
        /// <param name="path2"></param>
        /// <returns></returns>
        protected abstract Task<bool> ExistsAsyncInternal(string path);

        /// <summary>
        /// 存在キャッシュのクリア
        /// </summary>
        protected virtual void ClearExistsCahce()
        {
            ExistsCahce.Clear();
        }

        public abstract Task CopyAsync(string path, BlobFile file);

        public abstract Task<bool> DeleteAsync(BlobItem file);

        public abstract Task DownloadAsync(BlobItem item, Stream stream);

        public abstract Task DownloadAsync(BlobItem item, string localpath);

        public abstract Task<List<BlobItem>> GetFilesAsync(string id, int maxSize, bool flat = false);

        public abstract Task UploadAsync(BlobItem item, Stream stream);

        public abstract Task UploadAsync(BlobItem item, string localpath);

        public abstract Task GetMetadataAsync(BlobItem item);

        public abstract Task SetMetadataAsync(BlobItem item);

        public abstract Task CreateDirectoryAsync(BlobDirectory dire);

        public virtual Task<bool> CheckOutActionAsync(BlobUser user, BlobFile file)
        {
            return Task.FromResult(true);
        }

        public virtual Task<bool> CheckInActionAsync(BlobUser user, BlobFile file)
        {
            return Task.FromResult(true);
        }

        public abstract void Dispose();

        protected DateTimeOffset? ConvertTimezone(DateTime? time)
        {
            if (!time.HasValue) return null;
            if (string.IsNullOrEmpty(TimeZone)) return (DateTimeOffset)time.Value;
            var orgTimeZone = TimeZoneInfo.FindSystemTimeZoneById(TimeZone != null ? TimeZone : "UTC");
            var targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");

            if (time.Value.Kind == DateTimeKind.Utc)
            {
                return TimeZoneInfo.ConvertTime(time.Value, targetTimeZone);
            }
            else
            {
                return TimeZoneInfo.ConvertTime(time.Value, orgTimeZone, targetTimeZone);
            }

        }


        protected DateTimeOffset? ConvertTimezone(DateTimeOffset? time)
        {
            if (!time.HasValue) return null;
            if (string.IsNullOrEmpty(TimeZone)) return (DateTimeOffset)time.Value;
            var orgTimeZone = TimeZoneInfo.FindSystemTimeZoneById(TimeZone != null ? TimeZone : "UTC");
            var targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");
            if (orgTimeZone == targetTimeZone) return time;
            return TimeZoneInfo.ConvertTime(time.Value.DateTime, orgTimeZone, targetTimeZone);
        }

        /// <summary>
        /// メタ情報を設定
        /// </summary>
        public virtual void MergeMetaValue(Dictionary<string,string> meta, string key, string value)
        {
            meta[key] = value;
        }

        public virtual string GetOriginalUrl(string path)
        {
            return null;
        }

        public virtual CustomAuthInfo GetCustomAuth(string path)
        {
            if (authInfoList.ContainsKey(RootPath))
            {
                return authInfoList[RootPath];
            }
            return null;
        }

        public virtual void SetCustomAuth(CustomAuthInfo authInfo)
        {
            authInfoList[authInfo.Key] = authInfo;
        }

        private Dictionary<string, CustomAuthInfo> authInfoList
        {
            get
            {
                if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.Session == null)
                {
                    if (_authInfoList == null) _authInfoList = new Dictionary<string, CustomAuthInfo>();
                    return _authInfoList;
                }
                else
                {
                    if (System.Web.HttpContext.Current.Session["_authInfoList"] == null)
                    {
                        System.Web.HttpContext.Current.Session["_authInfoList"] = new Dictionary<string, CustomAuthInfo>();
                    }
                    return (Dictionary<string, CustomAuthInfo>)System.Web.HttpContext.Current.Session["_authInfoList"];
                }
            }
        }
        [ThreadStatic]
        Dictionary<string, CustomAuthInfo> _authInfoList;
    }
}
